package org.akomantoso.core.io.util;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.akomantoso.core.data.ModeTypeItem;
import org.akomantoso.core.data.QuotedStructure;
import org.akomantoso.core.data.QuotedText;
import org.akomantoso.core.data.StringItem;
import org.akomantoso.core.io.Input;
import org.akomantoso.core.io.InputConstants;
import org.akomantoso.core.io.util.group.InlineCMGroup;
import org.akomantoso.core.util.MapUtil;
import org.akomantoso.core.util.StringUtil;

/**
 * @author <a href="mailto:jacques.militello@gmail.com">Jacques Militello</a>
 */
public final class ModeTypeItemUtil {

	private ModeTypeItemUtil() {
	}

	private static final Map<String, Instantiator<ModeTypeItem>> MAP;

	public static void read(Input in, List<ModeTypeItem> elements) throws IOException {

		ModeTypeItem item = null;
		final String localName = in.getLocalName();

		int eventType;

		while (true) {
			eventType = in.readNext();

			switch (eventType) {
			case InputConstants.START_ELEMENT:
				elements.add(item = instantiate(in.getLocalName()));
				item.readExternal(in);
				break;
			case InputConstants.CHARACTERS:
				String tempString = in.readContent();
				if (!in.isWhiteSpace()) {
					elements.add(new StringItem(StringUtil.deleteAnyControlChar(tempString)));
				}
				break;
			case InputConstants.END_ELEMENT:
				if (localName.equals(in.getLocalName())) {
					return;
				}
			}
		}

	}

	static ModeTypeItem instantiate(String elementName) {
		final Instantiator<ModeTypeItem> instatiator = MAP.get(elementName);
		if (instatiator == null) {
			throw new RuntimeException("Tag [" + elementName + "] not supported for ModeTypeItem ?!?");
		}
		return instatiator.instantiate();

	}

	static {

		final Map<String, Instantiator<ModeTypeItem>> temp = new HashMap<String, Instantiator<ModeTypeItem>>();

		MapUtil.copy(InlineCMGroup.MAP, temp);

		// quotedStructure
		temp.put(QuotedStructure.ELEMENT, new Instantiator<ModeTypeItem>() {
			public QuotedStructure instantiate() {
				return new QuotedStructure();
			}
		});

		// quotedText
		temp.put(QuotedText.ELEMENT, new Instantiator<ModeTypeItem>() {
			public QuotedText instantiate() {
				return new QuotedText();
			}
		});

		MAP = Collections.unmodifiableMap(temp);

	}

}